﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Http;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using DataFetchTool.Entity;

namespace DataFetchTool
{
    public partial class DateFetchTool : Form
    {
        private readonly string[] BROSWER_LIST = { "tmall", "taobao" };

        ChromiumWebBrowser browser;

        private SQLHelper sqlHelper;

        private ServerCommunicator serverHelper;

        public DateFetchTool()
        {
            CefSharpSettings.LegacyJavascriptBindingEnabled = true;
            sqlHelper = new SQLHelper();
            InitializeComponent();
        }

        private async void DataFetchTool_Load(object sender, EventArgs e)
        {
            await StartCheckServer();
            var settings = new CefSettings()
            {
                Locale = "zh-CN",
                LogFile = "Debug.log", //You can customise this path
                LogSeverity = LogSeverity.Default, // You can change the log level
                EnableNetSecurityExpiration = false,
                UserDataPath = "UserData",
                CachePath = "Cache"
            };
            this.KeyPreview = true;
            var host = sqlHelper.ServiceHost;
            if (!host.EndsWith("/"))
            {
                host += "/";
            }
            if (host.Contains(":"))
            {
                txtUrl.Text = $"http://{host}authpage/index.html";
            }
            else
            {
                txtUrl.Text = host + "authpage/index.html";
            }
            Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
            browser = new ChromiumWebBrowser(txtUrl.Text)
            {
                LifeSpanHandler = new CustomLifeSpanHandler()
            };
            browser.Dock = DockStyle.Fill;
            browser.AddressChanged += Browser_AddressChanged;
            browser.RegisterAsyncJsObject("__com", serverHelper);
            pageContainer.Controls.Add(browser);
        }

        private async Task StartCheckServer()
        {
            var host = sqlHelper.ServiceHost;
            if (!string.IsNullOrWhiteSpace(host))
            {
                var serverHelper = new ServerCommunicator
                {
                    ServerHost = host
                };
                string result = await serverHelper.ServerLifeCheck();
                if (!string.IsNullOrEmpty(result))
                {
                    MessageBox.Show(result, "提示");
                    sqlHelper.ServiceHost = null;
                    await StartCheckServer();
                    return;
                }
                else
                {
                    this.serverHelper = serverHelper;
                }
            }
            else
            {
                var serviceHost = GetUserInputServiceHost();
                if (!string.IsNullOrWhiteSpace(serviceHost))
                {
                    var serverHelper = new ServerCommunicator
                    {
                        ServerHost = serviceHost
                    };
                    string result = await serverHelper.ServerLifeCheck();
                    if (!result.Equals(string.Empty))
                    {
                        MessageBox.Show(result, "提示");
                        await StartCheckServer();
                        return;
                    }
                    else
                    {
                        this.serverHelper = serverHelper;
                        sqlHelper.ServiceHost = serviceHost;
                    }
                }
                else
                {
                    await StartCheckServer();
                }
            }
        }

        private string GetUserInputServiceHost()
        {
            HostDialog dialog = new HostDialog();
            if (!string.IsNullOrWhiteSpace(sqlHelper.ServiceHost))
            {
                dialog.SetValue(sqlHelper.ServiceHost);
            }
            dialog.StartPosition = FormStartPosition.CenterParent;
            DialogResult result = dialog.ShowDialog();
            if (result.Equals(DialogResult.OK))
            {
                string url = dialog.GetValue();
                if (url.EndsWith("/"))
                {
                    return url.Substring(0, url.Length - 1);
                }
                return url;
            }
            return null;
        }

        private void Browser_AddressChanged(object sender, AddressChangedEventArgs e)
        {
            this.Invoke(new MethodInvoker(() =>
            {
                txtUrl.Text = e.Address;
            }));
        }

        private void DevTools_Click(object sender, EventArgs e)
        {
            browser.ShowDevTools();
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            browser.Load(txtUrl.Text);
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            browser.Reload();
        }

        private void btnForward_Click(object sender, EventArgs e)
        {
            if (browser.CanGoForward)
            {
                browser.Forward();
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            if (browser.CanGoBack)
            {
                browser.Back();
            }
        }

        private void DateFetchTool_FormClosing(object sender, FormClosingEventArgs e)
        {
            sqlHelper.Close();
            Cef.Shutdown();
        }

        internal class CustomLifeSpanHandler : ILifeSpanHandler
        {
            public bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
                return false;
            }

            public void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
            }

            public void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
            {
            }

            public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser,
                IFrame frame, string targetUrl, string targetFrameName,
                WindowOpenDisposition targetDisposition, bool userGesture,
                IPopupFeatures popupFeatures, IWindowInfo windowInfo,
                IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
            {
                newBrowser = null;
                chromiumWebBrowser.Load(targetUrl);
                return true;
            }
        }

        public async Task<T> CommonExecute<T>(string script)
        {
            JavascriptResponse execTask = await browser.EvaluateScriptAsync(script);
            if (!execTask.Success)
            {
                throw new Exception(execTask.Message);
            }
            return (T)execTask.Result;

        }

        public async Task<string> FetchData(string type)
        {
            string checkResult = await serverHelper.ServerLifeCheck();
            if (!checkResult.Equals(string.Empty)) return checkResult;
            serverHelper.LoadRules(browser);
            // 测试是否为商品页面
            bool ifItemPage = await CommonExecute<bool>($@"{serverHelper.Rules[type].testId}");
            if (!ifItemPage)
            {
                return "非商品页面，不能采集";
            }
            // 获取商品ID
            string itemId = await CommonExecute<string>($@"{serverHelper.Rules[type].fetchId}");
            // 获取商品标题
            string itemTitle = await CommonExecute<string>($@"{serverHelper.Rules[type].title}");
            // 获取商品原价
            string itemOriginalPrice = await CommonExecute<string>($@"{serverHelper.Rules[type].originalPrice}");
            // 获取商品卖价
            string itemSalePrice = await CommonExecute<string>($@"{serverHelper.Rules[type].salePrice}");
            // 获取商品图片集
            object imagesJSON = await CommonExecute<object>($@"{serverHelper.Rules[type].images}");
            // 获取sku信息
            object skuJSON = await CommonExecute<object>($@"{serverHelper.Rules[type].sku}");
            object propertyMaps = await CommonExecute<object>($@"{serverHelper.Rules[type].propertyMap}");
            // 获取sku图片信息
            object itemImageJSON = await CommonExecute<object>($@"{serverHelper.Rules[type].itemImages}");
            // 获取商品详情
            string descInfoHTML = await CommonExecute<string>($@"{serverHelper.Rules[type].desc}");

            FetchData data = new FetchData
            {
                mall = type,
                itemId = itemId,
                itemTitle = itemTitle,
                itemOriginalPrice = itemOriginalPrice,
                itemSalePrice = itemSalePrice ?? itemOriginalPrice,
                imagesJson = imagesJSON,
                skuJson = skuJSON,
                itemImageJson = itemImageJSON,
                attributeInfo = propertyMaps,
                descInfoHtml = descInfoHTML
            };
            string jsonData = JsonConvert.SerializeObject(data);
            if ("tmall".Equals(type))
            {
                return await serverHelper.PostTmallFetchData(jsonData, browser);
            }
            else
            {
                return await serverHelper.PostTaobaoFetchData(jsonData, browser);
            }
        }

        private async void btnFetch_Click(object sender, EventArgs e)
        {
            btnFetch.Enabled = false;
            try
            {
                string mallHost = await CommonExecute<string>(@"location.host.split('.')[1];");
                if (Array.Exists(BROSWER_LIST, i => i.Equals(mallHost)))
                {
                    string message = await FetchData(mallHost);
                    if (!message.Equals(string.Empty))
                    {
                        MessageBox.Show(message, "提示");
                    }
                }
                else
                {
                    MessageBox.Show("本页面不能采集数据", "提示");
                }
                btnFetch.Enabled = true;
            }
            catch (Exception exception)
            {
                btnFetch.Enabled = true;
                MessageBox.Show(exception.Message, "错误");
            }
        }

        private void txtUrl_OnKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                browser.Load(txtUrl.Text);
            }
        }

        private async void SettingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var originHost = sqlHelper.ServiceHost;
            var newHost = GetUserInputServiceHost();
            if (!string.IsNullOrWhiteSpace(newHost) && !originHost.Equals(newHost))
            {
                sqlHelper.ServiceHost = newHost;
                await StartCheckServer();
                var healthyHost = sqlHelper.ServiceHost;
                if (!healthyHost.EndsWith("/"))
                {
                    healthyHost += "/";
                }
                if (healthyHost.Contains(":"))
                {
                    txtUrl.Text = $"http://{healthyHost}authpage/index.html";
                }
                else
                {
                    txtUrl.Text = healthyHost + "authpage/index.html";
                }
                browser.Load(txtUrl.Text);
            }
        }
    }
}
